Spring Boot 2.0.0参考手册_中文版_Part IV_23

文章作者:Tyan
博客:noahsnail.com  |  CSDN  |  简书

Part IV. Spring Boot特性

这一部分进入Spring Boot细节部分。在这部分你会了解到你想使用和定制的一些重要特性。如果你还没准备好,你可以阅读第二部分“Getting started”和第三部分“Using Spring Boot”,可以对基础知识有个较好的认识。

23. SpringApplication

SpringApplication提供了一种很方便的方式来引导Spring应用,Spring应用可以从main()方法中启动。许多情况下你可以委托给静态方法SpringApplication.run

1
2
3
public static void main(String[] args) {
SpringApplication.run(MySpringConfiguration.class, args);
}

当你的应用启动时你应该看到类似于下面的东西:

1
2
3
4
5
6
7
8
9
10
11
12
 .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: v1.4.2.RELEASE

2013-07-31 00:08:16.117 INFO 56603 --- [ main] o.s.b.s.app.SampleApplication : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb)
2013-07-31 00:08:16.166 INFO 56603 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy
2014-03-04 13:09:54.912 INFO 41370 --- [ main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 8080
2014-03-04 13:09:56.501 INFO 41370 --- [ main] o.s.b.s.app.SampleApplication : Started SampleApplication in 2.992 seconds (JVM running for 3.658)

默认情况下会输出INFO日志信息,包括一些相关的启动细节例如启动应用的用户。

23.1 启动失败

如果你的应用启动失败,注册FailureAnalyzers有可能会提供专门的错误信息和解决这个问题的具体行动。例如,如果你启动一个8080端口的web应用并且这个端口已经被占用,你应该会看到类似于下面的内容:

1
2
3
4
5
6
7
8
9
10
11
***************************
APPLICATION FAILED TO START
***************************

Description:

Embedded servlet container failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

Spring Boot提供了许多FailureAnalyzer实现,你可以很容易添加自己的FailureAnalyzer实现。

如果没有失败分析器能处理这个异常,你仍可以显示完整的自动配置报告,从而更好的理解什么地方出问题了。为了实现这个你需要启用debug属性或启用org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializerDEBUG日志。

例如,如果你使用java -jar运行应用,你可以用下面的形式启用debug属性:

1
$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug

23.2 定制Banner

启动时打印的标语可以通过在classpath中添加一个banner.txt文件或者将banner.location设置为banner.txt文件的位置来修改。如果文件是一种不常见的编码方式,你可以设置banner.charset(默认是UTF-8)。除了文本文件之外,你也添加一个banner.gifbanner.jpgbanner.png图像文件到classpath中,或者设置一个banner.image.location属性。图像将被转换成ASCII艺术表示并打印在文本标语之上。

banner.txt内部你可以使用下面的任何占位符:

Table 23.1. Banner变量

Variable Description
${application.version} 你的应用的版本号在MANIFEST.MF中声明。 例如Implementation-Version: 1.0打印成1.0.
${application.formatted-version} MANIFEST.MF中的声明的应用版本号进行格式化显示(加上前缀v并用括号包裹)。例如(v1.0)
${spring-boot.version} 你使用的Spring Boot版本。例如1.4.2.RELEASE.
${spring-boot.formatted-version} 你使用的Spring Boot版本进行格式化显示加上前缀v并用括号包裹)。例如(v1.4.2.RELEASE)
${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME}) NAME是ANSI转义码的名字。更多细节请看AnsiPropertySource
${application.title} MANIFEST.MF中声明的应用标题。例如Implementation-Title: MyApp打印成MyApp.

如果你想自动生成一个标语你可以使用SpringApplication.setBanner(…​)方法。使用org.springframework.boot.Banner接口并实现你自己的printBanner()方法。

你也可以使用spring.main.banner-mode属性来决定标语是否必须在System.out(控制台)上输出,使用配置的日志(log)或一点也不用(off)。

如果你想在你的应用中禁用banner,YAML会将off映射为false,因此要确保添加引用。

1
2
3
spring:
main:
banner-mode: "off"

23.3 定制SpringApplication

如果你不喜欢默认的SpringApplication,你可以创建一个本地实例并定制它。例如,关闭你写的banner:

1
2
3
4
5
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}

 

传给SpringApplication的构造函数参数是Spring beans配置源。在大多数情况下将会引用@Configuration类,但它们也可以引用XML配置或应该扫描的包。

也可以使用application.properties文件配置SpringApplication。更多细节请看24章,『外部配置』。

完整的配置选项列表,请看SpringApplication文档。

23.4 流畅的构建器API

如果你需要构建ApplicationContext分层(多个具有父/子关系的上下文),或者你更喜欢使用fluent的构建器API,你可以使用SpringApplicationBuilder

SpringApplicationBuilder允许你链接多个方法调用,包括允许你创建分层的parentchild方法。

例如:

1
2
3
4
5
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);

当创建ApplicationContext分层时有一些限制,例如,子上下文必须包含web组件,父子上下文将使用同一个Environment。更完整的细节请看SpringApplicationBuilder文档。

23.5 应用事件和监听器

除了平常的Spring框架事件之外,例如ContextRefreshedEventSpringApplication会发送一些其它的应用事件。

ApplicationContext创建之前实际上会触发一些事件,因此你不能使用@Bean来注册这些监听器。你可以通过SpringApplication.addListeners(…​)SpringApplicationBuilder.listeners(…​)方法来注册这些监听器。

如果你想自动注册这些监听器,不管上下文的创建方式,你可以在你的工程中添加META-INF/spring.factories文件,并通过org.springframework.context.ApplicationListener作为key来引用你的监听器。

1
org.springframework.context.ApplicationListener=com.example.project.MyListener

当你的应用运行时,应用事件以下面的顺序发送:

  1. 在运行启动时发送ApplicationStartedEvent,除了监听器和初始化器注册之外,在进行任何处理之前发送。
  2. 当在上下文中使用的Environment已知时,发送ApplicationEnvironmentPreparedEvent,但发送是在上下文创建之前。
  3. 在再刷新启动之前,但在bean定义加载之后,发送ApplicationPreparedEvent
  4. 在再刷新之后,发送ApplicationReadyEvent,任何相关的回调函数都处理完成之后,意味着应用已经准备处理服务请求了。
  5. 如果启动时出现异常,发送ApplicationFailedEvent.

经常你不需要使用应用事件,但知道它们的存在是便利的。Spring Boot内部使用事件来处理大量的任务。

23.6 Web环境

SpringApplication会尝试创建代表你的合适的ApplicationContext类型。默认情况下,会使用AnnotationConfigApplicationContextAnnotationConfigEmbeddedWebApplicationContext,依赖于你是否在开发一个web应用。

使用的决定web environment的算法是相对简单的(基于现有的一些类)。如果你需要覆写默认值你可以使用setWebEnvironment(boolean webEnvironment)

完全控制ApplicationContext类型也是可能的,通过调用setApplicationContextClass(…​)使用。

当在JUnit测试时使用SpringApplication,经常需要调用setWebEnvironment(false)

23.7 访问应用参数

如果你需要访问传进SpringApplication.run(…​)中的应用参数,你可以注入org.springframework.boot.ApplicationArguments bean。ApplicationArguments接口提供了访问原始String[]和转换的optionnon-option参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.springframework.boot.*
import org.springframework.beans.factory.annotation.*
import org.springframework.stereotype.*

@Component
public class MyBean {

@Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
}

}

Spring Boot也在Spring Environment中注册CommandLinePropertySource。这也允许你使用@Value注解注入单个应对参数。

23.8 使用ApplicationRunner或CommandLineRunner

如果你需要在SpringApplication启动时运行一些特定的代码,你可以实现ApplicationRunnerCommandLineRunner接口。这两个接口以同样方式工作,并有一个单独的run方法,在SpringApplication.run(…​)之前会调用这个run方法。

CommandLineRunner接口提供了对应用参数的访问,应用参数作为一个简单的字符串数组,而ApplicationRunner使用前面描述的ApplicationArguments接口。

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.boot.*
import org.springframework.stereotype.*

@Component
public class MyBean implements CommandLineRunner {

public void run(String... args) {
// Do something...
}

}

另外,如果定义的CommandLineRunnerApplicationRunner beans必须以指定顺序调用,你可以实现org.springframework.core.Ordered接口或org.springframework.core.annotation.Order 注解。

23.9 应用退出

为了确保ApplicationContext在关闭时安全退出, 每个SpringApplication都会在JVM中注册一个关闭钩子。所有的标准Spring生命周期回调函数(例如DisposableBean接口,或@PreDestroy注解)都会被使用。

另外,当应用退出时,如果它们想返回一个特定的退出码,beans可以实现org.springframework.boot.ExitCodeGenerator接口。

23.10 Admin功能

如果应用想启用admin相关的功能,可以指定spring.application.admin.enabled属性。这会在平台MBeanServer上暴露SpringApplicationAdminMXBean。你可以使用这个功能远程的管理你的Spring Boot应用。对于任何服务包裹的实现这是很有用的。

如果你想知道应用运行的HTTP接口,通过关键字local.server.port可以得到这个属性。

 

当启用这个功能时要非常小心,因为MBean会暴露一个关闭应用的方法。

如果有收获,可以请我喝杯咖啡!